import os
import path
import syscall
import parker.log as *
import parker.util
import parker.cgroup
import compress.tgz
import libc_temp

var version = '0.1.1'

if util.arg_verbose() {
    tgz.verbose = true
    set_verbose()
}

logf('runner start version: %s', version)

// - read exe path
var exe_path = os.exe()
var workdir = path.dir(exe_path)
logf('workdir=%s', workdir)

// - extract tgz by exe
var tgz_buf = util.extract_tgz(exe_path)

// - mount namespace
util.mount_ns(workdir)

// - write tgz to mount ns
var tgz_path = path.join(workdir, 'parker.tag.gz')
var tgz_fd = syscall.open(tgz_path, syscall.O_CREAT|syscall.O_RDWR|syscall.O_TRUNC, 0644)

assertf(tgz_fd > 0, 'open tgz path %s fd %d exception', tgz_path, tgz_fd)

var len = syscall.write(tgz_fd, tgz_buf) catch err {
    assertf(false, 'write tgz to %s failed, err=%s', tgz_path, err.msg)
}

// - un tgz file
tgz.decode(workdir, tgz_path)
logf('tgz decode success')

// - read target
var target_path = util.read_target(workdir)
logf('read target_path %s success', target_path)

// - cgroup new
var cg = cgroup.make()

// - run target with cgroup
var pid = util.run_target(cg, target_path)

var sigfd = util.sig_notify()

// - listen sig or wait cmd
var sig_info = signalfd_siginfo_t{}
for true {
    var (result, status) = syscall.wait(pid, 1)
    if result != 0 { // pid  is down       
        logf('pid %d is exit status=%d', pid, status)

        // clear cgroup dir
        cg.clear()
        break
    }

    var len = syscall.read(sigfd, sig_info as cptr, sizeof(signalfd_siginfo_t)) catch err {
            // 暂时不用处理
            if err.msg == 'Resource temporarily unavailable' {
                // logf('not received any sig, will sleep')
            } else {
                assertf(false, 'read sigfd %d err=%s', sigfd, err.msg)
            }

            continue -1
    }
    // sig to the pid process but no operation is done
    // Resource temporarily unavailable
    if len != -1 {
        // 读取信号成功, 进行信号同步
        logf('read sig %d success', sig_info.ssi_signo)
        // sync the received sig to the pid
        syscall.kill(pid, sig_info.ssi_signo as int)
        logf('send sig=%d to pid=%d success', sig_info.ssi_signo, pid)
    }

    sleep(1)

    // logf('usleep 50ms, will next for')
}

logf('successful and exit')

